package com.jackrain.nea.wms.mq;

import com.alibaba.dubbo.common.utils.NetUtils;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.aliyun.openservices.ons.api.ConsumeContext;
import com.aliyun.openservices.ons.api.Message;
import com.aliyun.openservices.ons.api.exception.ONSClientException;
import com.aliyun.openservices.ons.api.impl.util.MsgConvertUtil;
import com.jackrain.nea.core.db.Tools;
import com.jackrain.nea.exception.NDSException;
import com.jackrain.nea.util.ApplicationContextHandle;
import com.jackrain.nea.util.ValueHolder;
import com.jackrain.nea.wms.mapper.WmsSqlMapper;
import com.jackrain.nea.wms.utils.ObjectToUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cglib.proxy.MethodInterceptor;
import org.springframework.cglib.proxy.MethodProxy;

import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.util.HashMap;
import java.util.List;

/**
 * Created by ZC 2017/5/31.
 */
@Slf4j
public class MQLogIntercept implements MethodInterceptor {

    @Override
    public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable {


        Object rev = null;

//        log.debug("Before invoke " + method.getName());
//        Object result =rev = methodProxy.invokeSuper(o, objects);
//        log.debug("After invoke" + method.getName());


        try {
            //执行织入的日志
            if ("consume".equals(method.getName())) {
                //1
                beforeConsume((Message) objects[0], (ConsumeContext) objects[1]);
                //2
                rev = methodProxy.invokeSuper(o, objects);
                //5
            } else if ("mqConsume".equals(method.getName())) {
                //3
                rev = methodProxy.invokeSuper(o, objects);
                //4
                AfterConsume((ValueHolder) rev, (Message) objects[0], (ConsumeContext) objects[1]);
            }
        } catch (Exception e) {
            //更新错误日志
            StringWriter sw = new StringWriter();
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            ThrowableConsume((Message) objects[0], (ConsumeContext) objects[1], sw.toString());

            //ons问题得重新消费并发送
            if ((e instanceof ONSClientException)) {
                throw e;
            }
            throw new NDSException(sw.toString());

        }

        return rev;
    }

    /**
     * MQ日志
     */
    public void beforeConsume(Message message, ConsumeContext context) {
        log.debug("------------AfterConsume----"+ message.getTopic()+ message.getKey()+message.getBody());


        try {
            //
            WmsSqlMapper sqlMapper = ApplicationContextHandle.getBean(WmsSqlMapper.class);
            //获取消息发送日志
            JSONObject whereKeys = new JSONObject();
            whereKeys.put("MSGKEY", message.getKey());
            List<HashMap> hashMaps = sqlMapper.select("ons_sendmonitor", new String[]{"id"}, whereKeys);
            long ons_sendmonitor_id = 0;
            if (hashMaps != null && hashMaps.size() > 0) {
                HashMap hashMap = hashMaps.get(0);
                ons_sendmonitor_id = ObjectToUtil.getLong(hashMap.get("id"), 0);
            }
            if (ons_sendmonitor_id <= 0) {
                //新增
                JSONObject insertKeys = new JSONObject();
                ons_sendmonitor_id = Tools.getSequence("ons_sendmonitor");
                insertKeys.put("ID", ons_sendmonitor_id);
                insertKeys.put("AD_CLIENT_ID", 37);
                insertKeys.put("OWNERID", 893);
                insertKeys.put("MODIFIERID", 893);
                insertKeys.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
                insertKeys.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
                insertKeys.put("ISACTIVE", "Y");
                insertKeys.put("PTYPE", "5");//ERP消息
                insertKeys.put("TOPIC", message.getTopic());
                insertKeys.put("TAG", message.getTag());
                insertKeys.put("MSGKEY", message.getKey());
                insertKeys.put("STATE", "1");//0:待发送,1:待消费,2:消费成功 默认待消费
                insertKeys.put("CONSUMER_ERROR", "N");//消费是否存在异常
                Serializable ser = MsgConvertUtil.objectDeserialize(message.getBody());
                if (ser instanceof JSONArray) {
                    JSONArray paramArray = JSONArray.parseArray(ser.toString());
                    insertKeys.put("PDESC", paramArray.toJSONString());
                } else if (ser instanceof JSONObject) {
                    JSONObject parapObject = JSONObject.parseObject(ser.toString());
                    insertKeys.put("PDESC", parapObject.toJSONString());
                }
                sqlMapper.insert("ons_sendmonitor", insertKeys);
            }
            log.debug("------------AfterConsume---ons_consumermq---start");

            JSONObject insertKeys = new JSONObject();
            insertKeys.put("ID", Tools.getSequence("ons_consumermq"));
            insertKeys.put("AD_CLIENT_ID", 37);
            insertKeys.put("ONS_SENDMONITORID", ons_sendmonitor_id);
            insertKeys.put("OWNERID", 893);
            insertKeys.put("MODIFIERID", 893);
            insertKeys.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
            insertKeys.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
            insertKeys.put("ISACTIVE", "Y");//
            insertKeys.put("ONS_XTYPE", "5");//云端消费ERP消息
            insertKeys.put("STATE", "0");//0未消费 1消费失败 2消费成功 3部分成功
            insertKeys.put("CONSUMERIP", NetUtils.getLocalAddress().getHostAddress());//
            insertKeys.put("MSGKEY", message.getKey());
            insertKeys.put("TOPIC", message.getTopic());
            insertKeys.put("TAG", message.getTag());
            sqlMapper.insert("ons_consumermq", insertKeys);
        } catch (Exception e) {
            e.printStackTrace();
            log.debug("------------AfterConsume---ons_consumermq---error");

        }
        log.debug("------------AfterConsume---ons_consumermq---end");


    }

    /**
     * MQ日志
     */
    public void AfterConsume(ValueHolder valueHolder, Message message, ConsumeContext context) throws Exception {

        log.debug("------------AfterConsume----" + valueHolder + message.getKey());

        WmsSqlMapper sqlMapper = ApplicationContextHandle.getBean(WmsSqlMapper.class);
        //回写发送消息日志
        JSONObject setKeys = new JSONObject();
        setKeys.put("STATE", "2");//0:待发送,1:待消费,2:消费成功 3已消费 默认待消费
        JSONObject whereKeys = new JSONObject();
        whereKeys.put("MSGKEY", message.getKey());
        sqlMapper.update("ons_sendmonitor", setKeys, whereKeys);
        //回写消费日志
        setKeys = new JSONObject();
        setKeys.put("STATE", "2");//0未消费 1消费失败 2消费成功 3部分成功
        if (valueHolder != null) {
            setKeys.put("PDESC", ObjectToUtil.getString(valueHolder.get("retStr"), ""));
        }
        whereKeys = new JSONObject();
        whereKeys.put("MSGKEY", message.getKey());
        sqlMapper.update("ons_consumermq", setKeys, whereKeys);

    }

    public void ThrowableConsume(Message message, ConsumeContext context, String error) throws Exception {

        log.debug("------------ThrowableConsume----" + message.getKey() + error);

        WmsSqlMapper sqlMapper = ApplicationContextHandle.getBean(WmsSqlMapper.class);
        //回写发送消息日志
        JSONObject setKeys = new JSONObject();
        setKeys.put("CONSUMER_ERROR", "Y");//是否存在错误
        setKeys.put("STATE", "3");//0待发送 1待消费 2消费成功 3已消费
        JSONObject whereKeys = new JSONObject();
        whereKeys.put("MSGKEY", message.getKey());
        sqlMapper.update("ons_sendmonitor", setKeys, whereKeys);
        //回写消费日志
        setKeys = new JSONObject();
        setKeys.put("STATE", "1");//0未消费 1消费失败 2消费成功 3部分成功
        setKeys.put("ERROR", error);
        whereKeys = new JSONObject();
        whereKeys.put("MSGKEY", message.getKey());
        sqlMapper.update("ons_consumermq", setKeys, whereKeys);

        recCloudErrorLog("云端消费错误", error, message);

    }

    /**
     * 记录日志
     *
     * @param name    错误标题
     * @param error   详细错误信息
     * @param message
     */
    private void recCloudErrorLog(String name, String error, Message message) {

        try {
            //记录日志
            JSONObject insertKeys = new JSONObject();
            insertKeys.put("ID", Tools.getSequence("oms_clouderror"));
            insertKeys.put("AD_CLIENT_ID", 37);
            insertKeys.put("OWNERID", 893);
            insertKeys.put("MODIFIERID", 893);
            insertKeys.put("CREATIONDATE", new Timestamp(System.currentTimeMillis()));
            insertKeys.put("MODIFIEDDATE", new Timestamp(System.currentTimeMillis()));
            insertKeys.put("ISACTIVE", "Y");
            insertKeys.put("NAME", name);
            insertKeys.put("PTYPE", "1");//服务器端
            insertKeys.put("ERRORINFO", error);
            insertKeys.put("IP", NetUtils.getLocalAddress().getHostAddress());
            insertKeys.put("ORIGMSGKEY", message.getKey());
            insertKeys.put("TOPIC", message.getTopic());
            insertKeys.put("TAG", message.getTag());
            Serializable ser = MsgConvertUtil.objectDeserialize(message.getBody());
            if (ser instanceof JSONArray) {
                JSONArray paramArray = JSONArray.parseArray(ser.toString());
                insertKeys.put("DUTEINFO", paramArray.toJSONString());
            } else if (ser instanceof JSONObject) {
                JSONObject parapObject = JSONObject.parseObject(ser.toString());
                insertKeys.put("DUTEINFO", parapObject.toJSONString());
            }
            WmsSqlMapper sqlMapper = ApplicationContextHandle.getBean(WmsSqlMapper.class);
            sqlMapper.insert("oms_clouderror", insertKeys);

        } catch (Exception e1) {
            e1.printStackTrace();
        }
    }


}
